<template>
  <el-container class="app-container" style="height: 100%; padding: 10px 0 0 10px">
    <el-aside width="200px" style="background-color: white; margin: 0; padding: 0">
      <el-form size="mini" @submit.native.prevent>
        <el-form-item>
          <el-input v-model="currPatTypeName" placeholder="请输入巡更类型名称" clearable prefix-icon="el-icon-search" />
        </el-form-item>
      </el-form>
      <div style="height: calc(100% - 50px); overflow: auto" v-loading="patTypeLoading">
        <el-tree
          class="tree-box"
          ref="tree"
          :data="patTypeTree"
          :props="{ label: 'patTypeName' }"
          node-key="patTypeId"
          highlight-current
          :filter-node-method="filterNode"
          default-expand-all
          @node-click="handleNodeClick"
        />
      </div>
    </el-aside>

    <el-main style="padding: 0 0 0 20px">
      <el-form ref="queryForm" :model="queryParams" size="mini" inline style="white-space: nowrap; overflow-x: auto" :class="{ disabled: disableAction }" @submit.native.prevent>
        <el-form-item>
          <header-select @selectProject="onSelectProject" style="line-height: normal" />
        </el-form-item>
        <el-form-item prop="spotName">
          <el-input v-model.trim="queryParams.spotName" placeholder="请输入点位名称" clearable @keyup.enter.native="handleQuery" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
          <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
          <template v-if="showBtns.add">
            <el-button type="primary" icon="el-icon-plus" @click="openAddItem" v-if="queryParams.projectId">新增</el-button>
            <el-popover placement="top" trigger="hover" content="请选择左侧项目" v-else>
              <el-button slot="reference" icon="el-icon-plus" style="margin-left: 10px">新增</el-button>
            </el-popover>

            <el-dropdown :disabled="fileUploading" v-if="showBtns.importSpot && queryParams.projectId">
              <el-button icon="el-icon-upload2" :loading="fileUploading" style="margin-left: 10px">{{ fileUploading ? '上传验证中' : '导入' }}</el-button>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item icon="el-icon-upload2" @click.native="$refs.uploadBtn.click">上传Excel</el-dropdown-item>
                <el-dropdown-item icon="el-icon-download" @click.native="$refs.templateAnchor.click">下载模板</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-form-item>
      </el-form>

      <el-table v-loading="listLoading" :data="list" size="small" height="calc(100% - 110px)">
        <el-table-column label="巡更类型" prop="patrolTypeName" min-width="200" />
        <el-table-column label="点位编码" prop="spotCode" min-width="100" />
        <el-table-column label="点位名称" prop="spotName" show-overflow-tooltip min-width="200" />
        <el-table-column label="负责人" show-overflow-tooltip min-width="100">
          <template slot-scope="{ row }">
            <el-link type="primary" class="ellipsis principal-names" @click="openSelectUser(row)" v-if="showBtns.edit">{{ row.principalNames }}</el-link>
            <span v-else>{{ row.principalNames }}</span>
          </template>
        </el-table-column>
        <el-table-column label="按楼层检查" align="center" min-width="90">
          <dict-tag slot-scope="{ row }" :options="yesOrNo" :value="row.isFloor" />
        </el-table-column>
        <el-table-column label="关联楼栋" prop="buildingName" show-overflow-tooltip min-width="80" />
        <el-table-column label="点位状态" align="center" width="80">
          <el-tag slot-scope="{ row }" size="small" :type="row.status ? 'primary' : 'info'">{{ row.status ? '启用' : '禁用' }}</el-tag>
        </el-table-column>
        <el-table-column label="操作" width="260">
          <template slot-scope="{ row }">
            <el-button size="mini" type="text" icon="el-icon-edit" @click="$refs.EditItem.open(row)" v-if="showBtns.edit">修改</el-button>
            <el-button size="mini" type="text" icon="el-icon-delete" :loading="row.removeLoading" @click="handleDelete(row)" v-if="showBtns.remove">删除</el-button>
            <el-button size="mini" type="text" icon="el-icon-turn-off" :loading="row.isEnableLoading" @click="toggleIsEnable(row)" v-if="row.showDisableBtn">禁用</el-button>
            <el-button size="mini" type="text" icon="el-icon-open" :loading="row.isEnableLoading" @click="toggleIsEnable(row)" v-else-if="row.showEnableBtn">启用</el-button>
            <el-button size="mini" type="text" icon="el-icon-tickets" @click="showChangeRecord(row)" v-if="showBtns.info">变更记录</el-button>
          </template>
        </el-table-column>
      </el-table>

      <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
    </el-main>

    <el-upload ref="fileUpload" class="hide" accept=".xls,.xlsx" :limit="1" :on-change="onChangeFile" action="" :auto-upload="false" :show-file-list="false">
      <span ref="uploadBtn">上传Excel</span>
    </el-upload>
    <a ref="templateAnchor" class="hide" target="_blank" :href="templateURL" download>下载模板</a>

    <EditItem ref="EditItem" v-model="showEditItem" @ok="getList" />
    <EditBuilder ref="EditBuilder" @ok="getList" />
    <ChangeRecord ref="ChangeRecord" />
  </el-container>
</template>
<script>
// 巡更点列表
import auth from '@/plugins/auth'
import { flatList2tree, removeEmptyArray, isLikeOrEqual } from '@/utils'
import { yesOrNo } from '@/utils/baseData'
import { listPatType, getSpot, delSpot, setSpotStatus, importSpot } from '@/api/cq/patrol'
import HeaderSelect from './components/HeaderSelect'
import EditItem from './components/EditSpot'
import EditBuilder from './components/EditSpotBuilder'
import ChangeRecord from './components/SpotBuilderChangeRecord'
const baseURL = process.env.VUE_APP_BASE_API
const templateURL = `${baseURL}/profile/template/excel/巡更点导入模版实例.xlsx`
export default {
  name: 'PatSpotList',
  components: { HeaderSelect, EditItem, EditBuilder, ChangeRecord },
  data() {
    return {
      yesOrNo,
      templateURL,
      listLoading: false,
      total: 0,
      list: [],
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        projectId: '',
        spotName: ''
      },
      showEditItem: false,
      patTypeLoading: false,
      patTypeTree: [],
      currPatTypeId: '', // 当前选中巡更类型ID
      currPatTypeName: '',
      fileUploading: false
    }
  },
  computed: {
    disableAction() {
      return this.patTypeLoading || this.listLoading
    },
    showBtns() {
      // 操作按钮权限
      const permCode = 'cq:patrol:spot'
      const edit = auth.hasPermi(`${permCode}:edit`)
      const add = auth.hasPermi(`${permCode}:add`)
      const remove = auth.hasPermi(`${permCode}:remove`)
      const info = auth.hasPermi(`${permCode}:info`)
      const enable = auth.hasPermi(`${permCode}:enable`)
      const disable = auth.hasPermi(`${permCode}:disable`)
      const importSpot = auth.hasPermi(`${permCode}:importSpot`)
      return { edit, add, remove, info, enable, disable, importSpot }
    }
  },
  watch: {
    currPatTypeName(val) {
      this.$refs.tree.filter(val)
    }
  },
  created() {
    this.getPatTypeTree()
  },
  methods: {
    onSelectProject(project) {
      const projectId = project?.id || ''
      this.queryParams.projectId = projectId
      if (projectId) this.getList()
    },
    filterNode(value, data) {
      return isLikeOrEqual(data, { like: { patTypeName: value } })
    },
    handleNodeClick(data) {
      if (!data.isLeaf) {
        // 解决当前项高亮丢失
        this.$nextTick(() => this.$refs.tree?.setCurrentKey(this.currPatTypeId))
        return
      }
      if (data.patTypeId === this.currPatTypeId) return
      this.currPatTypeId = data.patTypeId
      this.getList()
    },
    async getPatTypeTree() {
      this.patTypeLoading = true
      const res = await listPatType().catch(() => false)
      this.patTypeLoading = false
      if (res === false) return (this.patTypeTree = [])

      let data = res.data || []
      data = flatList2tree(data, { id: 'patTypeId' })
      data = removeEmptyArray(data)
      this.patTypeTree = data
    },
    async getList() {
      const { showBtns } = this
      const { projectId } = this.queryParams
      if (!projectId) {
        this.$message('请选择项目')
        return (this.list = [])
      }

      const opt = { ...this.queryParams, patrolTypeId: this.currPatTypeId }
      this.listLoading = true
      const res = await getSpot(opt).catch(() => false)
      this.listLoading = false
      if (res === false) return (this.list = [])

      const data = res.rows || []
      data.map(i => {
        i.isEnableLoading = false
        i.showDisableBtn = showBtns.disable && i.status
        i.showEnableBtn = showBtns.enable && !i.status

        i.removeLoading = false

        const builders = i.cqPatrolSpotBuilderList || []
        i.cqPatrolSpotBuilderList = builders
        i.principalNames = builders.map(r => r.userNickName).join(',')
      })
      this.list = data
      this.total = res.total || 0
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      // 注：部分字段重置
      this.currPatTypeId = ''
      this.currPatTypeName = ''
      this.resetForm('queryForm')
      this.getList()
      this.$nextTick(() => this.$refs.tree.setCurrentKey())
    },
    async handleDelete(item) {
      if (item.status) return this.msgInfo('启用的点位不允许删除')

      if (item.removeLoading) return
      const res1 = await this.$confirm(`确认删除：${item.spotName}？`, '警告', { type: 'warning' }).catch(() => false)
      if (res1 !== 'confirm') return

      item.removeLoading = true
      const res = await delSpot(item.patSpotId).catch(() => false)
      item.removeLoading = false
      if (res === false) return

      this.msgSuccess('删除成功')
      this.list.length > 1 ? this.getList() : this.handleQuery()
    },
    openAddItem() {
      const item = {
        projectId: this.queryParams.projectId,
        patrolTypeId: this.currPatTypeId || null
      }
      this.$refs.EditItem.open(item)
    },
    async toggleIsEnable(item) {
      const isEnable = item.status ? 0 : 1
      const name = isEnable === 1 ? '启用' : '禁用'
      const res1 = await this.$confirm(`确认${name}?`, '警告', { type: 'warning' }).catch(() => false)
      if (res1 !== 'confirm') return

      const opt = {
        patSpotId: item.patSpotId,
        status: isEnable
      }
      item.isEnableLoading = true
      const res = await setSpotStatus(opt).catch(() => false)
      item.isEnableLoading = false
      if (res === false) return

      this.$message.success(`已${name}`)
      this.getList()
    },
    async onChangeFile(file) {
      if (!file?.raw) return this.$message.warning('请选择文件')

      const formData = new FormData()
      formData.append('projectId', this.queryParams.projectId)
      formData.append('file', file.raw)
      const opts = { headers: { 'Content-Type': 'multipart/form-data' }, responseType: 'arraybuffer', rawRes: true }

      this.fileUploading = true
      const res = await importSpot(formData, opts).catch(() => false)
      this.fileUploading = false
      this.$refs.fileUpload.clearFiles()
      if (res === false) return

      const contentType = res.headers['content-type'] || ''
      // 下载 excel
      if (contentType.includes('application/vnd.ms-excel')) {
        this.msgError('模板校验失败，请查看下载的文件并更改')
        const elink = document.createElement('a')
        elink.download = file.name
        elink.style.display = 'none'
        elink.href = URL.createObjectURL(new Blob([res.data]))
        elink.click()
        return
      }

      // 解析 JSON
      if (contentType.includes('application/json')) {
        let data = {}
        try {
          // ArrayBuffer 转 json
          const enc = new TextDecoder('utf-8')
          const decodedStr = enc.decode(new Uint8Array(res.data))
          data = JSON.parse(decodedStr)
        } catch (err) {
          return this.msgError('响应数据解析失败')
        }
        if (data.code !== 200) return data.msg && this.msgError(data.msg)

        this.msgSuccess('上传成功')
        this.getList()
        return
      }

      this.msgError('未知错误')
    },
    openSelectUser(item) {
      const { projectId } = this.queryParams
      if (!projectId) return this.msgInfo('请选择项目')
      this.$refs.EditBuilder.open({ projectId, patSpotId: item.patSpotId })
    },
    showChangeRecord(item) {
      this.$refs.ChangeRecord.open({ patSpotId: item.patSpotId })
    }
  }
}
</script>
<style lang="scss" scoped>
.principal-names {
  display: inline;
  font-size: 12px;
  font-weight: normal;
}
</style>
